using Microsoft.EntityFrameworkCore;
using RAG.Domain.Entities.App;
using RAG.Domain.Repositories;
using RAG.Infrastructure.Data;
using RAG.Application.Services.Interfaces;
using RAG.Application.Dtos.Role;

namespace RAG.Application.Services.Implementations;

public class RoleService : IRoleService
{
    private readonly IRepository<Roles> _roleRepository;
    private readonly RagAIDbContext _context;

    public RoleService(IRepository<Roles> roleRepository, RagAIDbContext context)
    {
        _roleRepository = roleRepository;
        _context = context;
    }

    public async Task<IEnumerable<RoleDto>> GetAllRolesAsync()
    {
        var roles = await _context.Roles
            .Include(r => r.PermissionList)
            .ToListAsync();

        return roles.Select(r => new RoleDto
        {
            Id = r.Id,
            RoleName = r.RoleName,
            Description = r.Description,
            RoleType = r.RoleType,
            CreatedAt = r.CreatedAt,
            UpdatedAt = r.UpdatedAt,
            Permissions = r.PermissionList.Select(p => p.PermissionName).ToList()
        });
    }

    public async Task<RoleDto?> GetRoleByIdAsync(Guid id)
    {
        var role = await _context.Roles
            .Include(r => r.PermissionList)
            .FirstOrDefaultAsync(r => r.Id == id);

        if (role == null) return null;

        return new RoleDto
        {
            Id = role.Id,
            RoleName = role.RoleName,
            Description = role.Description,
            RoleType = role.RoleType,
            CreatedAt = role.CreatedAt,
            UpdatedAt = role.UpdatedAt,
            Permissions = role.PermissionList.Select(p => p.PermissionName).ToList()
        };
    }

    public async Task<RoleDto?> GetRoleByNameAsync(string roleName)
    {
        var role = await _context.Roles
            .Include(r => r.PermissionList)
            .FirstOrDefaultAsync(r => r.RoleName == roleName);

        if (role == null) return null;

        return new RoleDto
        {
            Id = role.Id,
            RoleName = role.RoleName,
            Description = role.Description,
            RoleType = role.RoleType,
            CreatedAt = role.CreatedAt,
            UpdatedAt = role.UpdatedAt,
            Permissions = role.PermissionList.Select(p => p.PermissionName).ToList()
        };
    }

    public async Task<RoleDto> CreateRoleAsync(RoleDto roleDto)
    {
        // 检查角色名称是否已存在
        var existingRole = await _context.Roles
            .FirstOrDefaultAsync(r => r.RoleName == roleDto.RoleName);
        
        if (existingRole != null)
        {
            throw new InvalidOperationException($"角色名称 '{roleDto.RoleName}' 已存在");
        }

        var role = new Roles
        {
            Id = Guid.NewGuid(),
            RoleName = roleDto.RoleName,
            Description = roleDto.Description,
            RoleType = roleDto.RoleType,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow
        };

        var createdRole = await _roleRepository.CreatedAsync(role);
        
        return new RoleDto
        {
            Id = createdRole.Id,
            RoleName = createdRole.RoleName,
            Description = createdRole.Description,
            RoleType = createdRole.RoleType,
            CreatedAt = createdRole.CreatedAt,
            UpdatedAt = createdRole.UpdatedAt,
            Permissions = new List<string>()
        };
    }

    public async Task<RoleDto> UpdateRoleAsync(Guid id, RoleDto roleDto)
    {
        var existingRole = await GetRoleByIdAsync(id);
        if (existingRole == null)
        {
            throw new InvalidOperationException($"角色ID '{id}' 不存在");
        }

        // 检查角色名称是否与其他角色冲突
        var duplicateRole = await _context.Roles
            .FirstOrDefaultAsync(r => r.RoleName == roleDto.RoleName && r.Id != id);
        
        if (duplicateRole != null)
        {
            throw new InvalidOperationException($"角色名称 '{roleDto.RoleName}' 已存在");
        }

        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null)
        {
            throw new InvalidOperationException($"角色ID '{id}' 不存在");
        }

        // 更新字段
        role.RoleName = roleDto.RoleName;
        role.Description = roleDto.Description;
        role.RoleType = roleDto.RoleType;
        role.UpdatedAt = DateTime.UtcNow;

        var updatedRole = await _roleRepository.UpdateAsync(role);
        
        return new RoleDto
        {
            Id = updatedRole.Id,
            RoleName = updatedRole.RoleName,
            Description = updatedRole.Description,
            RoleType = updatedRole.RoleType,
            CreatedAt = updatedRole.CreatedAt,
            UpdatedAt = updatedRole.UpdatedAt,
            Permissions = existingRole.Permissions
        };
    }

    public async Task<bool> DeleteRoleAsync(Guid id)
    {
        var role = await GetRoleByIdAsync(id);
        if (role == null)
        {
            return false;
        }

        // 检查角色是否被用户使用
        var usersUsingRole = await _context.Users
            .Where(u => u.Roles.Any(r => r.Id == id))
            .ToListAsync();

        if (usersUsingRole.Any())
        {
            var userNames = string.Join(", ", usersUsingRole.Select(u => u.UserName));
            throw new InvalidOperationException($"无法删除角色，该角色正在被以下用户使用: {userNames}");
        }

        await _roleRepository.DeleteAsync(id);
        return true;
    }

    public async Task<bool> AssignPermissionsToRoleAsync(Guid roleId, List<string> permissionNames)
    {
        var role = await _context.Roles
            .Include(r => r.PermissionList)
            .FirstOrDefaultAsync(r => r.Id == roleId);

        if (role == null)
        {
            return false;
        }

        var permissions = await _context.Permissions
            .Where(p => permissionNames.Contains(p.PermissionName))
            .ToListAsync();

        foreach (var permission in permissions)
        {
            if (!role.PermissionList.Any(p => p.Id == permission.Id))
            {
                role.PermissionList.Add(permission);
            }
        }

        role.UpdatedAt = DateTime.UtcNow;
        await _context.SaveChangesAsync();
        return true;
    }

    public async Task<bool> RemovePermissionsFromRoleAsync(Guid roleId, List<string> permissionNames)
    {
        var role = await _context.Roles
            .Include(r => r.PermissionList)
            .FirstOrDefaultAsync(r => r.Id == roleId);

        if (role == null)
        {
            return false;
        }

        var permissionsToRemove = role.PermissionList
            .Where(p => permissionNames.Contains(p.PermissionName))
            .ToList();

        foreach (var permission in permissionsToRemove)
        {
            role.PermissionList.Remove(permission);
        }

        role.UpdatedAt = DateTime.UtcNow;
        await _context.SaveChangesAsync();
        return true;
    }
} 